<template>
    <div v-move class="max-box">
  
        <div class="content" v-move>
            我是一个可以被鼠标拖动的盒子
        </div>
    </div>
</template>

<script setup lang="ts">

import { ref, Directive, DirectiveBinding } from 'vue';



// 定义一个自定义指令 v-move
const VMove: Directive<any, void> = (el: HTMLElement, bingding: DirectiveBinding) => {
    console.log('el', el);    // 这个 el 就是挂载 v-move 指定的元素
    // 获取到盒子右侧和底部可以移动到的最值
    const right = window.innerWidth - el.clientWidth
    const bottom = window.innerHeight - el.clientHeight
    console.log('盒子右下最值：', right, bottom);

    // 获取内部第一个div元素
    let moveElement: HTMLDivElement = el.firstElementChild as HTMLDivElement
    console.log('获取的元素', moveElement);   // 这里获取到的就是 header 所在的div元素

    // 鼠标按下的事件
    const mouseDown = (e: MouseEvent) => {
        let X = e.clientX - el.offsetLeft
        let Y = e.clientY - el.offsetTop
        // 鼠标移动事件
        const move = (e: MouseEvent) => {
            // 控制向左移动最左不能超出窗口左侧 且 向右移动最右不能让盒子超出窗口右侧
            let moveX = e.clientX - X < 0 ? 0 : ((e.clientX - X) > right ? right : e.clientX - X)
            // 控制向上移动最上不能超出窗口顶部 且 向下移动最下不能让盒子超出窗口底部
            let moveY = e.clientY - Y < 0 ? 0 : ((e.clientY - Y) > bottom ? bottom : e.clientY - Y)

            el.style.left = moveX + 'px'
            el.style.top = moveY + 'px'
        }
        document.addEventListener('mousemove', move)
        // 在鼠标抬起时去移除移动事件
        document.addEventListener('mouseup', () => {
            // 移除移动事件
            document.removeEventListener('mousemove', move)
        })
    }
    // 为获取到的div盒子绑定鼠标按下事件
    moveElement.addEventListener('mousedown', mouseDown)

}

</script>

<style lang="scss" scoped>
.max-box {
    width: 250px;
    min-height: 250px;
    background-color: #fff;
    position: absolute;
    top: 30%;
    left: 50%;

    .header {
        width: 100%;
        height: 30px;
        background-color: black;
        cursor: move;
    }

    .content {
        min-height: 250px;
        border: 2px solid black;
        border-top: 0;
        padding: 10px;
    }

}
</style>